import { Request } from 'express';
import http from 'http';
import https from 'https';
import {getLogger} from '../logger';

const logger = getLogger('ip-util');

// 保存请求对象，通过中间件注入
let currentRequest: Request | null = null;

/**
 * 设置当前请求对象
 */
export function setCurrentRequest(req: Request): void {
  currentRequest = req;
}

/**
 * 获取客户端IP地址
 */
export function getClientIp(): string {
  if (!currentRequest) {
    return '127.0.0.1';
  }

  const forwardedIps = currentRequest.headers['x-forwarded-for'] as string;
  
  if (forwardedIps) {
    // 如果存在多个IP，取第一个非内网IP
    const ips = forwardedIps.split(',');
    for (const ip of ips) {
      const trimmedIp = ip.trim();
      if (trimmedIp && !isInternalIp(trimmedIp)) {
        return trimmedIp;
      }
    }
  }

  return (
    currentRequest.headers['x-real-ip'] as string || 
    currentRequest.ip || 
    currentRequest.connection.remoteAddress || 
    '127.0.0.1'
  );
}

/**
 * 判断是否为内网IP
 */
function isInternalIp(ip: string): boolean {
  return (
    ip === '127.0.0.1' ||
    ip === '::1' ||
    ip.startsWith('10.') ||
    ip.startsWith('192.168.') ||
    /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(ip) ||
    ip.startsWith('fd') ||
    ip.includes('::ffff:')
  );
}

/**
 * 根据IP获取地理位置
 */
export async function getAddressByIp(ip: string): Promise<string> {
  // 如果是内网IP，直接返回内网标记
  if (isInternalIp(ip)) {
    return '内网IP';
  }

  try {
    // 使用第三方API获取位置信息
    // 此处使用免费的ip-api.com，生产环境建议使用更稳定的付费API
    const response = await httpGet(`http://ip-api.com/json/${ip}?lang=zh-CN`);
    const data = JSON.parse(response);
    
    if (data.status === 'success') {
      return `${data.country} ${data.regionName} ${data.city} ${data.isp}`;
    }
    
    return '未知位置';
  } catch (error) {
    logger.error(`获取IP[${ip}]位置信息失败`, error);
    return '未知位置';
  }
}

/**
 * 发起HTTP GET请求
 */
function httpGet(url: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const client = url.startsWith('https') ? https : http;
    const req = client.get(url, (res) => {
      if (res.statusCode !== 200) {
        reject(new Error(`HTTP请求失败，状态码: ${res.statusCode}`));
        return;
      }

      let data = '';
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        resolve(data);
      });
    });
    
    req.on('error', (error) => {
      reject(error);
    });
    
    req.setTimeout(5000, () => {
      req.destroy();
      reject(new Error('请求超时'));
    });
  });
}

export default {
  getClientIp,
  getAddressByIp,
  setCurrentRequest
}; 